[AWS CDK] スタックデプロイ時に「’null’ values are not allowed in templates」エラーが発生したので対処した話
こんにちは、CX事業本部 IoT事業部の若槻です。
今回は、AWS CDKでのスタックデプロイ時に'null' values are not allowed in templates
エラーが発生したので対処した話です。
事象
次のようなCDKスタックを作成して、CloudWatch Alarmのアラームをデプロイしようとしました。アラームのプロパティのうちevaluationPeriods
(いくつのピリオドを評価対象とするか)にはパラメーターストアから取得した値を使用します。その際にString形式となっている取得データを数値形式に変換するようにしています。
import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; import { StringParameter } from '@aws-cdk/aws-ssm'; export class AwsCdkAppStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const alarmConditionMinutesPeriod = StringParameter.valueForStringParameter( this, 'alarmConditionMinutesPeriod' ); new cloudwatch.Alarm(this, 'testAlarm01', { alarmName: 'testAlarm01', metric: new cloudwatch.Metric({ namespace: 'test', metricName: 'metric01', }), evaluationPeriods: Number(alarmConditionMinutesPeriod), //取得したテキスト形式の値を数値に変換 threshold: 10, statistic: cloudwatch.Statistic.MAXIMUM, comparisonOperator: cloudwatch.ComparisonOperator.LESS_THAN_OR_EQUAL_TO_THRESHOLD, period: cdk.Duration.minutes(1), treatMissingData: cloudwatch.TreatMissingData.MISSING, }); } }
パラメーターストアにevaluationPeriodsとしたい値をセットします。今回は30
です。
その上でCDKデプロイを行うと、次のようなエラーとなりました。
$ cdk deploy (中略) AwsCdkAppStack: deploying... [0%] start: Publishing 6f5c602aa4dee18ce9a3ff99ea9fa864e2d50ce67c1dd257554b2ef0fce1b4b1:current [100%] success: Published 6f5c602aa4dee18ce9a3ff99ea9fa864e2d50ce67c1dd257554b2ef0fce1b4b1:current AwsCdkAppStack: creating CloudFormation changeset... ❌ AwsCdkAppStack failed: Error [ValidationError]: [/Resources/testAlarm01525934D0/Type/EvaluationPeriods] 'null' values are not allowed in templates at Request.extractError (/Users/wakatsuki.ryuta/projects/cm-rwakatsuki/aws-cdk-app/node_modules/aws-cdk/node_modules/aws-sdk/lib/protocol/query.js:50:29) at Request.callListeners (/Users/wakatsuki.ryuta/projects/cm-rwakatsuki/aws-cdk-app/node_modules/aws-cdk/node_modules/aws-sdk/lib/sequential_executor.js:106:20) at Request.emit (/Users/wakatsuki.ryuta/projects/cm-rwakatsuki/aws-cdk-app/node_modules/aws-cdk/node_modules/aws-sdk/lib/sequential_executor.js:78:10) at Request.emit (/Users/wakatsuki.ryuta/projects/cm-rwakatsuki/aws-cdk-app/node_modules/aws-cdk/node_modules/aws-sdk/lib/request.js:688:14) at Request.transition (/Users/wakatsuki.ryuta/projects/cm-rwakatsuki/aws-cdk-app/node_modules/aws-cdk/node_modules/aws-sdk/lib/request.js:22:10) at AcceptorStateMachine.runTo (/Users/wakatsuki.ryuta/projects/cm-rwakatsuki/aws-cdk-app/node_modules/aws-cdk/node_modules/aws-sdk/lib/state_machine.js:14:12) at /Users/wakatsuki.ryuta/projects/cm-rwakatsuki/aws-cdk-app/node_modules/aws-cdk/node_modules/aws-sdk/lib/state_machine.js:26:10 at Request.<anonymous> (/Users/wakatsuki.ryuta/projects/cm-rwakatsuki/aws-cdk-app/node_modules/aws-cdk/node_modules/aws-sdk/lib/request.js:38:9) at Request.<anonymous> (/Users/wakatsuki.ryuta/projects/cm-rwakatsuki/aws-cdk-app/node_modules/aws-cdk/node_modules/aws-sdk/lib/request.js:690:12) at Request.callListeners (/Users/wakatsuki.ryuta/projects/cm-rwakatsuki/aws-cdk-app/node_modules/aws-cdk/node_modules/aws-sdk/lib/sequential_executor.js:116:18) { code: 'ValidationError', time: 2021-12-14T14:47:04.930Z, requestId: 'd358359f-5cfe-4df9-952e-3496feff6532', statusCode: 400, retryable: false, retryDelay: 524.6367273287826 } [/Resources/testAlarm01525934D0/Type/EvaluationPeriods] 'null' values are not allowed in templates
対処、解決
エラーメッセージを読むと、EvaluationPeriods
プロパティでnull
が指定されてしまっているためエラーになっているように読み取れます。
AwsCdkAppStack failed: Error [ValidationError]: [/Resources/testAlarm01525934D0/Type/EvaluationPeriods] 'null' values are not allowed in templates
パラメーターストアから取得したalarmConditionMinutesPeriod
の値が何らかの理由でnull
となってしまっているようです。
そこで色々調べたり試したりしたのですが、結論としては、alarmConditionMinutesPeriod
をNumber()
関数を使わず、as unknown as number
による型アサーションで数値形式とすることにより解決しました。
import * as cloudwatch from '@aws-cdk/aws-cloudwatch'; import { StringParameter } from '@aws-cdk/aws-ssm'; export class AwsCdkAppStack extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) { super(scope, id, props); const alarmConditionMinutesPeriod = StringParameter.valueForStringParameter( this, 'alarmConditionMinutesPeriod' ); new cloudwatch.Alarm(this, 'testAlarm01', { alarmName: 'testAlarm01', metric: new cloudwatch.Metric({ namespace: 'test', metricName: 'metric01', }), evaluationPeriods: alarmConditionMinutesPeriod as unknown as number, //型アサーションをするように修正 threshold: 10, statistic: cloudwatch.Statistic.MAXIMUM, comparisonOperator: cloudwatch.ComparisonOperator.LESS_THAN_OR_EQUAL_TO_THRESHOLD, period: cdk.Duration.minutes(1), treatMissingData: cloudwatch.TreatMissingData.MISSING, }); } }
上記修正をした上でスタックをデプロイすると正常に行うことができました。
$ cdk deploy (中略) AwsCdkAppStack: deploying... [0%] start: Publishing 6f5c602aa4dee18ce9a3ff99ea9fa864e2d50ce67c1dd257554b2ef0fce1b4b1:current [100%] success: Published 6f5c602aa4dee18ce9a3ff99ea9fa864e2d50ce67c1dd257554b2ef0fce1b4b1:current AwsCdkAppStack: creating CloudFormation changeset... ✅ AwsCdkAppStack Stack ARN: arn:aws:cloudformation:ap-northeast-1:XXXXXXXXXXXX:stack/AwsCdkAppStack/8aee57f0-4ad8-11ec-a443-0e5be759ac01
作成されたアラームを確認すると、ちゃんと30分となっています。
コンソールからだと少し分かりづらいのでCLIでも見てみると、こちらからもEvaluationPeriods
が30
となっていることが確認できますね。
$ aws cloudwatch describe-alarms --alarm-names "testAlarm01" { "MetricAlarms": [ { "AlarmName": "testAlarm01", "AlarmArn": "arn:aws:cloudwatch:ap-northeast-1:XXXXXXXXXXXX:alarm:testAlarm01", "AlarmConfigurationUpdatedTimestamp": "2021-12-14T14:59:06.403000+00:00", "ActionsEnabled": true, "OKActions": [], "AlarmActions": [], "InsufficientDataActions": [], "StateValue": "INSUFFICIENT_DATA", "StateReason": "Unchecked: Initial alarm creation", "StateUpdatedTimestamp": "2021-12-14T14:59:06.403000+00:00", "MetricName": "metric01", "Namespace": "test_", "Statistic": "Maximum", "Dimensions": [], "Period": 60, "EvaluationPeriods": 30, "Threshold": 10.0, "ComparisonOperator": "LessThanOrEqualToThreshold", "TreatMissingData": "missing" } ], "CompositeAlarms": [] }
以上